package br.cin.ufpe.corba.examples.navigator;


import java.io.Serializable;
import java.util.HashMap;

import javax.swing.tree.TreePath;

import br.cin.ufpe.corba.ORB;
import br.cin.ufpe.corba.namingservice.Name;
import br.cin.ufpe.corba.namingservice.NameComponent;
import br.cin.ufpe.corba.namingservice.NamingContextExt;
import br.cin.ufpe.corba.namingservice.NamingContextHelper;
import br.cin.ufpe.corba.namingservice.binding.Binding;
import br.cin.ufpe.corba.namingservice.binding.BindingIterator;
import br.cin.ufpe.corba.namingservice.binding.BindingList;
import br.cin.ufpe.corba.namingservice.binding.BindingType;

public class NamingServiceModel extends AbstractTreeModel implements Serializable {

	private static final long serialVersionUID = -455438912840175801L;
	
	private Binding root;
	private HashMap<Binding, NamingContextExt> namingContexts;
    private HashMap<NamingContextExt, BindingList> cache;
    
    public NamingServiceModel(ORB orb) {
        this( NamingContextHelper.narrow(orb.resolve_initial_references("NameService")) );
    }

    public NamingServiceModel( NamingContextExt rootNc ) {
        this.root = new Binding(new NameComponent(""), BindingType.CONTEXT);
        this.namingContexts = new HashMap<Binding, NamingContextExt>();
        this.cache = new HashMap<NamingContextExt, BindingList>();
        
        this.namingContexts.put(root, rootNc);
    }

    public Object getRoot() {
        return this.root;
    }

    public Object getChild( Object parent, int index ) {
    	Binding selectedBinding = null;
    	
    	Binding binding = (Binding) parent;
    	NamingContextExt nc = namingContexts.get(binding);
    	BindingList bindings = getBindings(nc);
        BindingIterator iter = bindings.iterator();
    	
        while (iter.has_next_one() && index >= 0) {
   			selectedBinding = iter.next_one();
   			index--;
    	}
        
        return selectedBinding;
    }

    public int getChildCount( Object parent ) {    	
    	int result = 0;
    	
    	Binding binding = (Binding) parent;
    	NamingContextExt nc = this.namingContexts.get(binding);
    	BindingList list = getBindings(nc);    	
    	BindingIterator iter = list.iterator();
    	while (iter.has_next_one()) {
    		iter.next_one();
   			result++;
    	}
    	
       return result;
    }

	private BindingList getBindings(NamingContextExt nc) {		
    	if (!cache.containsValue(nc)) {
    		BindingList list = nc.list(100);
    		
    		BindingIterator iter = list.iterator();
        	while (iter.has_next_one()) {
        		Binding binding = iter.next_one();
        		if (binding.getType() == BindingType.CONTEXT) {
        			NamingContextExt childNc = NamingContextHelper.narrow(nc.resolve(new Name(binding.getName().toString())));
        			this.namingContexts.put(binding, childNc);
        		}
        	}
        	
    		cache.put(nc, list);
    	}    	    
    	
    	return cache.get(nc);
	}

    public boolean isLeaf( Object node ) {
    	Binding binding = (Binding) node;
        return binding.getType() == BindingType.OBJECT;
    }

    public void valueForPathChanged( TreePath path, Object newValue ) {
    }

    public int getIndexOfChild( Object parent, Object child ) {
       return -1;
    }

	public void refresh() {
		NamingContextExt rootNc = this.namingContexts.get(root);
		
		this.namingContexts = new HashMap<Binding, NamingContextExt>();
        this.cache = new HashMap<NamingContextExt, BindingList>();        
        this.namingContexts.put(root, rootNc);		
	}
}


